﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CodeStatisticsTool
{
    public delegate void ThreadCall(Action action);

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public string LastSelectPath = null;

        string IgDir = ".git;.vs;bin;obj;packages";
        string IgFileTypes = "*.dll;*.pdb;*.cache;*.exe;*.zip;*.eot;*.ttf;*.woff;*.png;*.user;*.nupkg;*.rtf;*.psd1;*.psm1;*.gitattributes;*.gitignore;*.ico;*.svg;*.map;";

        private void HandleAllFiles(string path, Action<string> fileaction)
        {
            if (!Directory.Exists(path))
                return;

            var ig_dir_list = IgDir.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var item in Directory.GetFiles(path))
                fileaction(item);

            foreach (var item in Directory.GetDirectories(path))
                if (!Path.GetFileName(item).StartsWith(".") && !ig_dir_list.Contains(Path.GetFileName(item)))
                    HandleAllFiles(item, fileaction);
        }

        private IEnumerable<string> GetAllFileTypes(string path)
        {
            List<string> file_types = new List<string>();
            HandleAllFiles(path, (file) => { file_types.Add(Path.GetExtension(file)); });
            return file_types.Distinct();
        }

        private void button_SelectPath_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            if (!string.IsNullOrEmpty(LastSelectPath))
                dialog.SelectedPath = LastSelectPath;

            var dr = dialog.ShowDialog();
            if (dr == DialogResult.OK)
            {
                LastSelectPath = dialog.SelectedPath;

                string SelectPath = dialog.SelectedPath;
                List<string> Paths = new List<string>();
                Paths.AddRange(textBox_SelectPath.Text.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
                Paths.Add(SelectPath);
                Paths = Paths.Distinct().ToList();
                textBox_SelectPath.Text = string.Join(";", Paths); ;

                string[] IgFileTypeList = IgFileTypes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                // 开始统计都有哪些文件类型
                List<string> file_types = new List<string>();

                foreach (var item in textBox_SelectPath.Text.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    file_types.AddRange(GetAllFileTypes(item));
                }

                file_types = file_types.Distinct().ToList();

                textBox_FileTypes.Text = string.Join(";", file_types.Select(n => string.Format("*{0}", n)).Where(n => !IgFileTypeList.Contains(n)));
            }
        }

        private void MainTheadCall(Action action)
        {
            if (InvokeRequired)
                Invoke(new ThreadCall(MainTheadCall), new[] { action });
            else
                action();
        }

        private new void Handle()
        {
            long line = 0;
            long empy_line = 0;

            foreach (var item in textBox_SelectPath.Text.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                HandleAllFiles(item, file =>
                {
                    string[] IgFileTypeList = textBox_FileTypes.Text.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                    if (IgFileTypeList.Contains("*" + Path.GetExtension(file)))
                    {
                        var encoding = FileEncodingHelper.GetType(file);
                        StreamReader sr = new StreamReader(file, encoding);
                        string body = sr.ReadToEnd();
                        sr.Close();

                        foreach (var text in body.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            ++line;
                            if (string.IsNullOrEmpty(text))
                                ++empy_line;
                        }

                        MainTheadCall(() =>
                        {
                            richTextBox1.AppendText(body + "\r\n");
                            richTextBox1.ScrollToCaret();

                            Text = string.Format("{0} {1} {2}", line, empy_line, file);
                        });
                    }
                });
            }

            MainTheadCall(() =>
            {
                button_SelectPath.Enabled = true;
                button_Start.Enabled = true;

                Text = string.Format("完成统计 共计{0}行 空行{1}行", line, empy_line);
            });
        }

        private void button_Start_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = string.Empty;

            button_SelectPath.Enabled = false;
            button_Start.Enabled = false;
            new Thread(() => { Handle(); }) { IsBackground = true }.Start();
        }
    }
}
